import {
  useEffect,
  useState,
  useContext,
  useMemo,
  forwardRef,
  ForwardedRef,
  useImperativeHandle,
} from 'react';
import { useBoolean } from 'ahooks';
import { useTranslation } from 'react-i18next';
import { cloneDeep, isArray, isObject } from 'lodash-es';
import { FaArrowsLeftRightToLine, FaListUl, FaRotateRight, FaDownload } from 'react-icons/fa6';
import { Table as AntdTable, TableProps, Card, Space, Tooltip, Dropdown } from 'antd';
import ExcelJS from 'exceljs';
import { v4 } from 'uuid';
import QueryForm, { IFormProps } from 'src/components/QueryForm';
import CustomColumnsModal from './components/CustomColumnsModal';
import { IBaseTableResonseWrap } from 'src/interface';
import { ContentContext } from 'src/context/ContentContext';
import type { ColumnsType } from 'antd/es/table';
import { ScreenEnum } from 'src/interface/theme';

interface IProps extends TableProps<any> {
  rowKey: string;
  titleNode?: React.ReactNode;
  left?: React.ReactNode;
  right?: React.ReactNode;
  toolbar?: React.ReactNode;
  request?: (...args: any[]) => Promise<any>;
  showRefresh?: boolean;
  showCustom?: boolean;
  showDownload?: boolean;
  showSize?: boolean;
  formProps?: IFormProps;
  requestAfterFilter?: (...args: any[]) => Record<string, any>;
  dataSource?: Array<Record<string, any>>;
  downloadName?: string;
}

type TableSize = 'large' | 'middle' | 'small';

function Table(props: IProps, ref: ForwardedRef<{ onRefresh: () => void }>) {
  const {
    titleNode,
    showCustom = true,
    showSize = true,
    showDownload = true,
    showRefresh = true,
    toolbar,
    formProps,
    columns,
    left,
    right,
    request,
    dataSource,
    pagination,
    rowKey,
    requestAfterFilter,
    size,
    downloadName,
    ...rest
  } = props;
  const [searchData, setSearchData] = useState<Record<string, any>>({});
  const [loading, { setTrue, setFalse }] = useBoolean(false);
  const [visible, { setTrue: setVisibleTrue, setFalse: setVisibleFalse }] = useBoolean(false);
  const [tableSize, setTableSize] = useState<TableSize>(size ?? 'middle');
  const [tableData, setTableData] = useState<Array<Record<string, any>>>([]);
  const [column, setColumn] = useState(columns);
  const [pageInfo, setPageInfo] = useState({
    current: 1,
    pageSize: 10,
    total: 0,
    ...pagination,
  });
  const [showPagination, setShowPagination] = useState<boolean>(!!pagination);
  const containerWidth = useContext(ContentContext);

  const { t } = useTranslation();

  const scrollX = useMemo(() => {
    let currentWidth = 0;
    columns?.forEach((item) => {
      if (item.width) {
        currentWidth += Number(item.width);
      }
    });
    return currentWidth > containerWidth ? currentWidth : containerWidth - 200;
  }, [containerWidth, columns]);

  const toolbarClass = 'cursor-pointer text-base h-[16px]';

  const onPageSizeChange = (page: number, pageSize: number) => {
    const newPageInfo = {
      ...pageInfo,
      current: page,
      pageSize,
    };
    setPageInfo(newPageInfo);
  };

  const getTableData = async (queryData?: Record<string, any>) => {
    if (dataSource) {
      return setTableData(cloneDeep(dataSource));
    }
    if (request) {
      setTrue();
      try {
        const pages = showPagination ? { size: pageInfo.pageSize, current: pageInfo.current } : {};
        let data = await request({ ...searchData, ...queryData, ...pages });
        setShowPagination(!!data?.records);
        data?.total &&
          setPageInfo({
            ...pageInfo,
            total: data.total,
          });
        data = isArray(data)
          ? data
          : isObject(data) && (data as IBaseTableResonseWrap<any>).records
            ? (data as IBaseTableResonseWrap<any>).records
            : [];
        data = requestAfterFilter ? requestAfterFilter(data) : data;
        setTableData(data);
      } catch (err) {
        console.log(err);
      } finally {
        setFalse();
      }
    }
  };

  const onRefresh = () => {
    getTableData();
  };

  const onDownload = () => {
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet('Sheet1');
    // 添加表头
    const headerRow = columns
      ?.filter((column) => column.key !== 'action')
      .map((column) => column.title);
    worksheet.addRow(headerRow);

    function addRow(source: any) {
      const formattedRowData = [] as any[];
      columns?.forEach((column) => {
        formattedRowData.push(source[(column as any).dataIndex]);
      });
      worksheet.addRow(formattedRowData);
      // 递归处理子节点
      if (source.children) {
        source.children.forEach((child: any) => {
          addRow(child);
        });
      }
    }

    // 添加表格数据
    (dataSource || tableData).forEach((source) => {
      addRow(source);
    });
    workbook.xlsx.writeBuffer().then((buffer) => {
      // 创建 Blob 对象
      const blob = new Blob([buffer], {
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      });
      // 创建下载链接并点击下载
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = downloadName ? downloadName : `${v4().replace('-', '')}.xlsx`;
      link.click();
    });
  };
  const onSubmit = async (data: Record<string, any>) => {
    setSearchData(data);
    getTableData(data);
  };

  const customColumns = useMemo(() => {
    return (columns ?? [])
      ?.filter((column) => column.key !== 'action')
      .map((column) => {
        return {
          label: column.title as string,
          value: (column as any).dataIndex ?? column.key,
        };
      });
  }, [columns]);

  const onSaveColumns = (values: string[]) => {
    const newColumns = [] as ColumnsType<any>;
    (columns ?? []).forEach((item) => {
      if (values.includes((item as any).dataIndex ?? item.key)) {
        newColumns.push(item as any);
      }
    });
    setColumn(newColumns);
    setVisibleFalse();
  };

  useEffect(() => {
    getTableData();
  }, []);

  useImperativeHandle(
    ref,
    () => ({
      onRefresh,
      data: tableData,
    }),
    [tableData],
  );

  return (
    <>
      {formProps && formProps.schemas?.length > 0 && (
        <Card bodyStyle={{ paddingBottom: 0 }}>
          <QueryForm {...formProps} loading={loading} onSubmit={onSubmit} />
        </Card>
      )}
      <Card bodyStyle={{ padding: 16 }} className="mt-[16px]">
        {titleNode}
        <div className="flex justify-between mb-[16px]">
          <div>
            <Space>{left}</Space>
          </div>
          <div className="flex justify-end items-center">
            <Space size="middle">
              {right}
              {showRefresh && (
                <Tooltip title={t('main.table.refresh')}>
                  <FaRotateRight className={toolbarClass} onClick={onRefresh} />
                </Tooltip>
              )}
              {showDownload && (
                <Tooltip title={t('main.table.download')}>
                  <FaDownload className={toolbarClass} onClick={onDownload} />
                </Tooltip>
              )}
              {showSize && (
                <Tooltip title={t('main.table.size')}>
                  <Dropdown
                    placement="bottomRight"
                    trigger={['click']}
                    menu={{
                      items: [
                        { label: t('main.table.size_config.large'), key: 'large' },
                        { label: t('main.table.size_config.middle'), key: 'middle' },
                        { label: t('main.table.size_config.small'), key: 'small' },
                      ],
                      onClick: ({ key }) => setTableSize(key as TableSize),
                    }}>
                    <FaArrowsLeftRightToLine className={toolbarClass} />
                  </Dropdown>
                </Tooltip>
              )}
              {showCustom && containerWidth > ScreenEnum.MD && (
                <Tooltip title={t('main.table.custom')}>
                  <FaListUl className={toolbarClass} onClick={() => setVisibleTrue()} />
                </Tooltip>
              )}
              {toolbar}
            </Space>
          </div>
        </div>
        <AntdTable
          pagination={
            showPagination && {
              ...pagination,
              ...pageInfo,
              onChange: onPageSizeChange,
            }
          }
          scroll={{ x: scrollX }}
          rowKey={(row) => row[rowKey]}
          {...rest}
          columns={column}
          dataSource={tableData}
          loading={loading}
          size={tableSize}></AntdTable>
      </Card>
      <CustomColumnsModal
        open={visible}
        columns={customColumns}
        onSaveColumns={onSaveColumns}
        onCancel={() => setVisibleFalse()}
      />
    </>
  );
}

export default forwardRef(Table);
